1999 wurde in der Forschung (Collins et al.) ermittelt, dass die ASA-Klassifizierung des körperlichen Zustands, das Alter, Bluttransfusionen während der Operation und die Dauer von Operationen einen Aufschluss darüber geben, ob der Krankenhausaufenthalt des Patienten länger als gewöhnlich ausfallen wird.
Des Weiteren gibt es zahlreiche Studien, bspw. die Forschung von Biber et al. (2012), Singler et al. (2013) oder Ogliari et al. (2022) die festgestellt haben, dass es eine Korrelation zwischen dem Alter von Patienten und der Verweildauer in Notaufnahmen gab.
Dieser Frage möchten wir gerne nachgehen und versuchen, die Aufenthaltsdauer im Krankenhaus vorherzusagen.
Data
Uns liegen Daten von nicht-kardiochirurgischen Patienten vor, welche sich von August 2016 bis Juni 2017 einer Routine- oder Notoperation am Seoul National University Hospital, Seoul, Korea, unterzogen. Von den 7.051 in Frage kommenden Fällen wurden Fälle mit lokaler Anästhesie (239), unvollständiger Aufzeichnung (279) und Verlust von wesentlichen Datenspuren (145) ausgeschlossen. Schließlich wurden 6.388 Fälle (91 %), die eine Allgemeinanästhesie, Spinalanästhesie und Sedierung/Analgesie erhielten, in den Datensatz aufgenommen. Der Datensatz besteht aus intraoperativen Vitaldaten und perioperativen klinischen Informationen von 6.388 Fällen.
Die Vitaldaten umfassen bis zu 12 Wellenform- und 184 numerische Datenspuren, die von mehreren Anästhesiegeräten erfasst wurden, die den Patienten während der Operation eingesetzt wurden.
Die Daten wurden nicht vorverarbeitet, da das reale Rauschen in den Vitaldaten für die Entwicklung praktischer Überwachungsalgorithmen sehr wichtig ist.
Insgesamt 74 perioperative klinische Informationsparameter und 34 Zeitreihen perioperativer Laborergebnisse werden zur Verfügung gestellt, um die Interpretation der Beziehung zu den intraoperativen Vitalzeichen zu erleichtern.
Research Question
Wir stellen uns die Frage, welche dem Krankenhaus vorliegenden Daten die Aufenthaltsdauer von Patienten beeinflusst. Da der Datensatz des Seoul National University Hospital (Seoul, Korea) eine Vielzahl von möglichen Variablen enthält werden wir uns vorerst mit den aus der Literatur erwähnten Zusammenhängen beschäftigen.
Wir berechnen eine weitere Variable “op_duartion”. Sie zeigt die Dauer einer Operation an. Dafür subtrahieren wir von der Variablen “opend” die Variable “opstart”.
Code
df['op_duration']=df['opend']-df['opstart']
Wir benennen einige Variablen um:
“caseend” bezeichnet das Ende eines Falls, vom Startpunkt 0, daher bennen wir diese Variable “record_duration”
Die Variable “icu_days” bezeichnet die Aufenthaltsdauer im Krankenhaus (icu), daher bennen wir diese Variable “length_of_stay”
Da wir uns unter der Variable “intraop_ebl” wenig vorstellen konnten, benennen wir diese in “estimated_blood_loss” um.
Die Spalte “age” enthält u.a. die Zeichen “>89” und “0.7”. Daher wird das Größer-als-Zeichen entfernt und die Werte gerundet, damit es zu int umwandelt werden kann.
print("Missing values in 'estimated_blood_loss':",df['estimated_blood_loss'].isnull().sum())print("Missing values in 'op_duration':",df['op_duration'].isnull().sum())print("Missing values in 'length_of_stay':",df['length_of_stay'].isnull().sum())print("Missing values in 'bmi':",df['bmi'].isnull().sum())print("Missing values in 'asa':",df['asa'].isnull().sum())print("Missing values in 'age':",df['age'].isnull().sum())print("Missing values in 'recording_duration':",df['recording_duration'].isnull().sum())print("Missing values in 'sex':",df['sex'].isnull().sum())
Missing values in 'estimated_blood_loss': 0
Missing values in 'op_duration': 0
Missing values in 'length_of_stay': 0
Missing values in 'bmi': 0
Missing values in 'asa': 133
Missing values in 'age': 0
Missing values in 'recording_duration': 0
Missing values in 'sex': 0
Lediglich die Spalte ‘asa’ hat 133 NAs. Wir werden diese Variable mit Hilfe eines Boxplots genauer betrachten um zu entscheiden wie wir damit umgehen.
Von den 6.388 Werten lassen sich zwei Ausreißer erkennen. Im folgenden Boxplot sind diese noch einmal deutlich zu erkennen. Um unser Modell nicht von diesen zu beeinflussen, werden wir diese Ausreißer heraus nehmen. Wir nehmen Aufzeichnung mit einer “length_of_stay” größer als 50 Tagen aus den Daten heraus.
Aufgrund unserer Projektmotivation heraus nutzen wir die dort erwähnten Variablen. Zusätzlich nehmen wir noch die Variable “bmi” hinzu. Diese wird zwar nicht erwähnt, zeigt jedoch auf eine andere Art als die ASA-Klassifizierung (Variable “asa”) auch den Körperlichen Zustand eines Patienten. Aus der Projektmotivation ist auch zu entnehmen, dass wir die Krankenhausaufenhaltsdauer anhand dieser Prädiktoren bestimmen möchten.
Wir können eine starke Interkorrelation zwischen “op-duration” und “recording_duration” erkennen. Wir erkennen eine logisch nachvollziehbare, eindeutige, negative Übereinstimmung zwischen den Variablen “sex_F” und “sex_M”. Dass diese Variablen unser Modell nicht stören, werden wir uns für eine entscheiden und nur die Variable “sex_F” in das Modell einbeziehen und definieren daher X und Y neu. Die Korrelation der Prädiktoren mit der Variablen “length_of_stay” ist sehr gering.
Nun teilen wir den Datensatz in einen Trainings- und einen Testdatensatz auf.
Code
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)
Methodology
Lineare Regression
Wir beginnen nun ein Regressionsmodell aufzustellen
Code
reg = LinearRegression()
Nun erstellen wir die Kreuzvalidierung der Daten mit 5 Folds
Code
scores = cross_val_score(reg, X_train, y_train, cv=5, scoring='neg_mean_squared_error') *-1# store cross-validation scoresdf_scores = pd.DataFrame({"lr": scores})# reset index to match the number of foldsdf_scores.index +=1alt.Chart(df_scores.reset_index()).mark_line( point=alt.OverlayMarkDef()).encode( x=alt.X("index", bin=False, title="Fold", axis=alt.Axis(tickCount=5)), y=alt.Y("lr", aggregate="mean", title="Mean squared error (MSE)"))
Im nächsten Schritt passen wir das Modell an die Trainingsdaten an.
Code
reg.fit(X_train, y_train)
LinearRegression()
In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook. On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
LinearRegression()
Wir lassen uns nun die Regressionsgerade unsereres Modells berechnen.
Code
intercept = pd.DataFrame({"Name": ["Intercept"],"Coefficient":[reg.intercept_]} )# make a slope tableslope = pd.DataFrame({"Name": features,"Coefficient": reg.coef_})# combine estimates of intercept and slopestable = pd.concat([intercept, slope], ignore_index=True, sort=False)round(table, 3)
Name
Coefficient
0
Intercept
-0.175
1
recording_duration
0.000
2
age
-0.016
3
asa
0.980
4
bmi
-0.035
5
op_duration
0.000
6
estimated_blood_loss
0.001
7
sex_F
0.131
Nun möchten wir sehen, wie gut unser Modell ist. Dafür prognostizieren wir Werte für die Aufenthaltsdauer (“length_of_stay”) auf Basis der Testdaten. Um das Modell bewerten zu können berechnen wir Gütemaße für die prognostizierten Werte. Diese sind R-squared (R²), Adjusted R-Squared (Adjusted R²), den Rooted-Mean-Squared-Error (RMSE), den Mean-Squared-Error (MSE) und den Mean-Absolute-Error (MAE).
Nun möchten wir prüfen, ob unser Modell mit weniger Variablen besser wird, da beispielsweise eine starke Interkorrelation zwischen op-duration und recording_duration erkennbar ist. Wir gehen dafür entsprechend der Vorwärtseliminierung vor. Daher betrachten wir zuerst, wie wichtig welche Variable für unser Modell ist. Wir werden im Anschluss unser Modell der Reihe nach mit den wichtigsten Variablen aufbauen und die Gütemaße berechnen, bis diese nicht mehr besser werden. Hauptausschlaggebend wird für uns das adjusted R² sein.
Das Adjusted R² hat sich nicht weiter verbessert, wir liegen jedoch weiter unter dem Wert für das Modell mit allen Prediktoren, daher fügen wir die Variable “estimated_blood_loss” zum Modell hinzu und nehmen die Variable “sex_F” wieder heraus.
Das Modell verschlechtert sich. Wir prüfen nun, ob es unser Modell verbessert, wenn wir die “op_duration” im Vergleich zum eben berechneten Modell hinaus nehmen, Hintergrund ist, dass die “op_duration” und “recording_duration” eine starke Interkorrelation gezeigt hatten.
Wir erhalten also mit den Variablen “recording_duration”, “age”, “asa” und “bmi” die besten Ergebnisse.
Lasso-Regressionsmodell
Wir werden nun ein Lasso-Regressionsmodell mit unseren Daten erstellen. Zuerst werden wir daher die Daten zu standardisieren, sodass unser Lasso-Regressionsmodell bestmöglich performt. Bedeutet, wir entfernen den Mittelwert und skalieren die Variablen auf eine Einheitsvarianz. Dies führen wir für Trainings- und Testdaten durch. Im Anschluss definieren wir unser Modell und integrieren gleichzeitig eine Kreuzvalidierung.
In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook. On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
LassoCV(cv=5, random_state=0)
Wir berechnen nun den Alpha-Wert für unser Lasso-Regressionsmodell
Code
reg.alpha_
0.0007694571302528419
Code
# Fit the model to the complete training dataregla = Lasso(alpha=reg.alpha_)regla.fit(X_train, y_train)
Lasso(alpha=0.0007694571302528419)
In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook. On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
Lasso(alpha=0.0007694571302528419)
Wir lassen uns nun die Regressionsgerade unsereres Lasso-Regressionsmodells berechnen.
Code
# interceptintercept = pd.DataFrame({"Name": ["Intercept"],"Coefficient":[reg.intercept_]} )# make a slope tableslope = pd.DataFrame({"Name": features,"Coefficient": reg.coef_})# combine estimates of intercept and slopestable = pd.concat([intercept, slope], ignore_index=True, sort=False)round(table, 3)
Die Werte haben sich weiter verbessert. Wir werden diese nun aber im nächsten Abschnitt noch einmal gegenüberstellen.
Results
Durch die Datenanalyse konnten wir erkennen, dass unsere Vorhersagevariable “length_of_stay” eine sehr große Streuung besitzt. Zudem konnten wir Zusammenhänge der Variablen betrachten und unser Lineares Regressionsmodell dementsprechend bestmöglich aufbauen. Störfaktoren in Form von Korrelation zwischen den Prädiktorvariablen wie “sex_M” und “sex_F” (r = -1,0) und “op_duration” und “recording_duration” (r = 0,989) wurden aufgezeigt und konnten bei der Modellerstellung berücksichtigt werden. Über die Methode der Vorwärtseliminierung konnten wir erkennen, dass ein Modell mit den Variablen “recording duration”, “age”, “asa” und “bmi” die besten Ergebnisse liefert. Nun können wir uns noch einmal die Ergebnisse, in Form der berechneten Gütemaße, des besten Linearen Regressionsmodells, des Lasso Regressionsmodells und des gradient boosting Modells gegenüber ansehen.
Bei der Gegenüberstellung der Modelle fällt auf, dass das Lineare Regressionsmodell anhand aller Gütemaße mit Ausnahme des Mean-Absolut-Error besser abschneidet als das Lasso-Regressionsmodell. Das Modell mit Gradient boosting fällt bei allen Gütemaßen am besten aus und ist daher zu bevorzugen.
Lineares Regressionsmodell:
Unser Modell sagt mit den Variablen “recording_duration”, “age”, “asa” und “bmi” die Aufenthaltsdauer von Patienten am besten voraus. Dennoch sehen wir in unserem Modell nur ein kleines adj. R², was für eine geringe Güte des Modells spricht. Nur etwa 14,3% der Variabilität der Aufenthaltsdauer werden durch das Modell erklärt.
Lasso Regressionsmodell:
Wir sehen ein kleines Adjusted R² unseres Modells, was eine geringe Güte des Modells bedeutet. Die Güte ist sogar noch etwas unter der des linearem Regressionsmodells. Etwa 11,2% der Variabilität der Aufenthaltsdauer wird durch das Modell erklärt.
Gradient Boosting:
Wir sehen weiterhin ein kleines Adjusted R² unseres Modells, was für eine geringe Güte des Modells spricht. 40,3% der Variabilität der Aufenthaltsdauer werden durch das Modell erklärt.
Wie bereits erwähnt fällt auf, dass das Lineare Regressionsmodell tendenziell dem Lasso Regressionsmodell zu bevorzugen ist, da alle Gütemaße mit Ausnahme des Mean-Absolut-Error beim Linearen Regressionsmodell besser ausfallen als beim Lasso-Regressionsmodell. Das Modell mit Gradient boosting schneidet bei allen Gütemaßen besser ab, als die beiden anderen Modelle und ist daher diesen gegenüber zu bevorzugen.
Anhand des MAE, Mean Absolute Error, erkennen wir den Durchschnitt der absoluten Differenz zwischen den von unserem Modell prognostizierten Werten und den tatsächlichen Werten. In unserem besten Modell bedeutet dies also, dass unser Modell die durchschnittlich die Aufenthaltsdauer um 0,55 Tage überschätzt. Im Falle, dass unser Modell im Krankenhaus verwendet würde, würde man tendenziell die Dauer 0,55 Tage länger planen, als diese tatsächlich ist. Der MSE, Mean Squared Error, zeigt uns den erwarteten, quadratische Abstand des prognostizierten Wertes zum tatsächlichen. Bei unserem besten Modell sind das 2,5 Tage.
Der RMSE, Root Mean Squared Error ist eine Erweiterung von MSE und ist definiert als die Quadratwurzel des mittleren quadratischen Fehlers. Diese Kennzahl erreicht bei unserem besten Modell einen Wert von 1,6 Tagen. Bedeutet unser bestes Modell liegt durchschnittlich 1,6 Tage von der tatsächlichen Aufenthaltsdauer entfernt.
Discussion + Conclusion
Anhand der im “Results”-Teil beschriebenen geringen Güte unseres Modells, des RMSE und MAE würden wir einem Krankenhaus nicht dazu raten mit diesen Variablen und diesem Modell zu versuchen die Aufenthaltsdauer der Patienten zu prognostizieren. Bei einer durchschnittlichen Aufenthaltsdauer von 0,55 Tagen (alle Daten) bzw. 0,51 Tagen (Nachdem wir Aufenthaltstage >50 heraus genommen haben) einen RMSE von 1,6 Tagen zu haben scheint uns definitiv nicht gut genug.
Mögliche Verbesserungen wären: Über Stratified sampling Gruppen bilden, um so Stichproben auszuwählen. Gruppen könnten beispielsweise sein:
„Abteilungen“ in welchen die Patienten behandelt werden
Art der Operation
handelt es sich um eine geplante oder eine Notoperation
Weiterhin wäre es auch möglich gewesen Variablen mit einzubeziehen, welche über die Forschungsfrage hinaus gehen. Hier wären ebenfalls die Variablen „Abteilungen“ in welchen die Patienten behandelt werden, Art der Operation und Notoperation denkbare Variablen gewesen.